
function AlemScene(webglObj){
	
	BuildingScene.call(this);
	
	
	this.CONSTANTS = {EXTRUDE_CORRIDOR : 0, EXTRUDE_OTHERS: 40, PAREDES: false, BEVEL_ESCALERAS: true, SPRITE_HEIGHT : 8};
	
	var _webglObj = webglObj;
	var _scene = this.getScene();//TODO ver como hacer esto mejor (herencia)
	var _camera = null;
	
	var _this = this;
	this.animateTreeSelection = true;
	
	var materialBuilder = new MaterialBuilder();
	var meshBuilder = new MeshBuilder(materialBuilder);
	var _objectBuilder = new builderSceneObjects(meshBuilder, materialBuilder, _this);
//	var _objectBuilder = new builderSceneObjects(new MeshBuilder());
	this.getObjectBuilder = function(){
		return _objectBuilder;
	};
	
	this.levelsShown = null;
	this.activeLevels = null;
	this.activate = function(){
		//console.log("FLY",this.levelsShown, this.activeLevels);
		//CONTROLLER_JERARQUIA_SPACES.setState(this.levelsShown, this.activeLevels);
//		var obj = CONTROLLER_JERARQUIA_SPACES.showLevel(_ubicacionInicial.edificio, _ubicacionInicial.nivel, true, true);
//		if (obj) ANIMATOR.reposicionarCamaraFromTree(BUILDING_TARGET_POSITION, obj.nivelesActuales , obj.nivelesAnteriores, false, "level",null, _this.animateTreeSelection);
		$("#divBotonesFLY").css('display','inline');
		$("#btnControles").show();
		$("#controlesFLY").show();
	};
	
	this.deactivate = function(){
		$("#divBotonesFLY").css('display','inline');
		$("#btnControles").hide();
		$("#controlesFLY").hide();
	};
	
	var _ubicacionInicial = {edificio: "Alem", nivel: "0", piso: "CZ_PB"}; //el space va a ser el de referencia
	
	this.getPanelsConfiguration = function(){
		var config =
		 {
				 dataRenderer :{ enabled : true, show: false},
				 stats :{ enabled : true, show: true},
				 contexto :{ enabled : true, show: false},
				 animacion :{ enabled : true, show: false},
				 camara :{ enabled : true, show: true},
				 ubicacion :{ enabled : false, show: true},
				 tab_busqueda :{ show: false},
				 tab_jerarquia :{ show: true},
				 tree: {animacionOnOff: true , animacion2d3d: _this.animateTreeSelection},
		 }
		
		return config
	};
	
	
	var domContainer = _webglObj.getDomContainer();
	var projector = new THREE.Projector();
	
	//marcadores para mostrar el inicio/fin de una animacion
	var renderer = _webglObj.getRenderer();
	var _meshFlechaInicio = null, 
	_meshFlechaDestino = null; //mesh para la flechas de inicio y fin del camino
	
	var escenaPlanos = null;//escenaPlanos = muestra solo los 3 planos (en gris)
	var escenaCompleta = null;//escenaCompleta = muestra fuente, arboles, autos, etc
	
	var directionalLight, pointLight, ambientLight;	 //luces

	var _camaraFlyContext = null, _camaraFly = null, controls = null;
	
	//+++++++++ PARA DEBUG ++++++++++
	var objDrag; //DEBUG.cubo para debuggear el drag
	this.getDragDebugCube = function(){return objDrag;}//DEBUG.
	//+++++++++ fin PARA DEBUG ++++++++++
	
	
	//DEPRECATED
	var nombreCalles = [];
	this.getNombreCalles = function(){return nombreCalles;};
	//DEPRECATED
	
	//API
	this.addToScene = function(object){_scene.add(object);};
	this.getCamera = function(){return _camera;};
	this.getScene = function(){return _scene;};
	this.getCameraControls = function(){return controls;};
	this.getMarcadorInicio = function(){return _meshFlechaInicio;};
	this.getMarcadorFinal = function(){return _meshFlechaDestino;};
	this.moverContextoEscena = function(altura){escenaPlanos.position.y = altura;};
	this.getContextFlyCamera = function(){return _camaraFlyContext};
	
	
	
	//INIT
	crearCamaras(_scene);	
	crearLuces(_scene);
	crearMundo(_scene);
	
	//+++++++++ CONTEXTO ++++++++++
	var parameters = {webglObject : _webglObj,
					camera : _camaraFlyContext,
					width : 200,
					height : 200,
					posX : $(domContainer).width() - 200,
					posY : 0
				  };
	var contextViewport = new Contexto(parameters);
	//+++++++++ fin CONTEXTO ++++++++++
	
	this.context = contextViewport;
	
	
	
	
	
	
	var SELECTED = 0;
	var inicial = null;
	this.handleEvent = function(params){
		
		if (!params || !params.type){return;}
		
		switch(params.type){
			case "mousewheel":
				 
				 var vector = new THREE.Vector3( params.xNorm, params.yNorm, 0.5 );
				 projector.unprojectVector( vector, _camera );
	
				 var valor = params.delta *Math.abs(controls.object.position.y/15);
				 var ray = new THREE.Ray( _camera.position, vector.subSelf( _camera.position ).normalize() );
				 ray.direction.normalize().multiplyScalar(valor);
				// controls.object.position.addSelf(ray.direction);
				 var pos = controls.object.position.clone();
				 pos.addSelf(ray.direction);
				 controls.setPosition(pos);	
				 
				break;
				
			case 'mousedown':
				
				var vector = new THREE.Vector3( params.xNorm, params.yNorm, 0.5 );
			 	projector.unprojectVector( vector, _camera );

			 	var ray = new THREE.Ray( _camera.position, vector.subSelf( _camera.position ).normalize() );
			
				///////////////////////SPRITEE////////////////////////////////////
				var sprt = CONTROLLER_JERARQUIA_SPACES.getTextXY(ray);
				if(sprt && params.kind == 'drag'){
					CONTROLLER_PAGE_STATE.showActiveSprite(sprt, params.x, params.y);
					return -1;
				}
				/////////////////////////FIN SPRITE //////////////////////////////////////
				
				var altura = CONTROLLER_JERARQUIA_SPACES.getActiveLevelHeight();
				var inter_ = UTILS.intersectPlaneXZ(ray, altura);

				inicial = inter_.clone();
				if ( ray.direction.y < -0.03 ) { //Si intersecta "cerca" (mira para abajo)
					if (DEBUGGING_DRAG) {
						var objDrag = webglObject.getDragDebugCube();
						objDrag.visible = true;
						objDrag.position.copy(inter_);
						objDrag.position.y = CONTROLLER_JERARQUIA_SPACES.getActiveLevelIndex()*100;
					}
					SELECTED = 1;
				}
				
				break;
				
			case 'mousemove':
				
				if (params.kind == 'drag'){
					var vector = new THREE.Vector3( params.xNorm, params.yNorm, 0.5 );
					projector.unprojectVector( vector, _camera );

					var ray = new THREE.Ray( _camera.position, vector.subSelf( _camera.position ).normalize() );
										
					var altura = CONTROLLER_JERARQUIA_SPACES.getActiveLevelHeight();
					var inter_ = UTILS.intersectPlaneXZ(ray, altura);
					
					//if (true){
					if (SELECTED){
						var val = inter_.subSelf( inicial);
						
						controls.desplazarXZAbsoluto(val);//desplazar
						//_camera.position.subSelf(val);
						return;
					}	
				} else if (params.kind == 'rotation'){
					var x1 = params.xOld;
					var x2 = params.x;
					var y1 = params.yOld;
					var y2 = params.y;
					
					var ang1 = Math.PI/1080 * Math.abs(x1-x2);
					var ang2 = Math.PI/1080* Math.abs(y1-y2);
					 
					 if (x1 < x2){ang1 *= -1;}
					 if (y1 < y2){ang2 *= -1;}
					 
					controls.rotarHorizontalmente(ang1);
					controls.rotarPitch(ang2);
				}
			
				break;
				
			case 'mouseup' :
				
				SELECTED = 0;
				break;
				
			case 'resize':
				
				var SCREEN_WIDTH = $(domContainer).width();
                var SCREEN_HEIGHT = $(domContainer).height();
                _camera.aspect = SCREEN_WIDTH/SCREEN_HEIGHT;
                _camera.updateProjectionMatrix();
                renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
                renderer.setScissor( 0,0, SCREEN_WIDTH, SCREEN_HEIGHT );
                renderer.setViewport( 0,0, SCREEN_WIDTH, SCREEN_HEIGHT);
                contextViewport.resize();
                
				break;
				
			case 'keydown':
				controls.keydown(params.event);
				break;
				
			case 'keyup':
				controls.keyup(params.event);
				break;	
				
			case 'panel_camara_desplazamiento' :
				
				var val = Math.abs(controls.object.position.y/75);
				var constante = (val > 100)? val : 20;
				var radio = params.vector.length();
				var range = (radio/(params.width/2));
				Math.pow(range,2);
//				Math.pow(range,4);
	
				var valor = range*constante;
				controls.desplazarXZ(params.vector.normalize(), valor);//desplazar
				break;
			
			case 'panel_camara_orientacion' :
				
				var vector = params.vector.negate();
				
				var constante = Math.PI/180;
				
				var ang1 = constante*(params.vector.x/(params.width/2));
				var ang2 = constante*(params.vector.z/(params.height/2));
				 
				//orientacion
				controls.rotarHorizontalmente(ang1);
				controls.rotarPitch(ang2);
				break;
				
			case 'panel_camara_zoom' :
				
				var val = Math.abs(controls.object.position.y/15);
				var valor = (val > 100)? val : 20;
				if (params.action == 'zoomOut') valor *= -1;
				
				controls.translate(new THREE.Vector3(0,0,1), valor);//Z
				break;
				
			case 'tree_select_building' :
				
				var obj = CONTROLLER_JERARQUIA_SPACES.showBuilding(params.nombreEdificio, true); //apply = false (no queremos que cambie la opacidad desde ese metodo)
				ANIMATOR.reposicionarCamaraFromTree(params.centroid, obj.nivelesActuales , obj.nivelesAnteriores, params.climbY, "level",null, _this.animateTreeSelection);
				break;
				
			case 'tree_select_level' :
				hideAllLevels()
				var obj = CONTROLLER_JERARQUIA_SPACES.showLevel(params.nombreEdificio, params.nombreNivel, true, true); 
				ANIMATOR.reposicionarCamaraFromTree(params.centroid, obj.nivelesActuales , obj.nivelesAnteriores, params.climbY, "level",null, _this.animateTreeSelection);
				break;
				
			case 'tree_select_floor' :
				hideAllLevels()
				var obj = CONTROLLER_JERARQUIA_SPACES.showLevel(params.nombreEdificio, params.nombreNivel, true, true); 
				ANIMATOR.reposicionarCamaraFromTree(params.centroid, obj.nivelesActuales , obj.nivelesAnteriores, params.climbY, "floor", null, _this.animateTreeSelection);
				break;
				
			case 'tree_select_space' :
				hideAllLevels()
				var callback2 = function(){
					var pos = UTILS.toScreenXY($("#canvas_webgl"), params.centroid, _camera);
					
					var sp = CONTROLLER_JERARQUIA_SPACES.getSprite( params.nombreEdificio, params.nombreNivel, params.nombrePiso, params.idSpace);
					CONTROLLER_PAGE_STATE.showActiveSprite(sp, pos.x, pos.y);
				};
				
				var obj = CONTROLLER_JERARQUIA_SPACES.showLevel(params.nombreEdificio, params.nombreNivel, true, true); 
				ANIMATOR.reposicionarCamaraFromTree(params.centroid, obj.nivelesActuales , obj.nivelesAnteriores, params.climbY, "space", callback2, _this.animateTreeSelection);
				break;
		}
		
		
	}
	
	function hideAllLevels(){
		for (var idNivel in _this.objetos3D){
			if (_this.objetos3D[idNivel].opacity != 1)
			UTILS.setOpacity(_this.objetos3D[idNivel], 0);
		}
	}
	
	//-----------------------------------------------------------
	//---------------------- ANIMATE ------------------------
	//-----------------------------------------------------------
	this.animate = function(){
		controls.update();	//actualiza los controles de la camara	
		
//		pointLight.position.x = _camera.position.x;
//		pointLight.position.z = _camera.position.z;
//		pointLight.position.y = _camera.position.y;
		pointLight.position.copy(controls.object.position);
		pointLight.position.y += 100
		
		// directionalLight.position.copy(controls.object.position);
		
		if (WEBGL.getRenderizarContexto())//renderizamos contexto?
		{
			renderer.enableScissorTest( false );
			renderer.clear();
			renderer.enableScissorTest( true );	
		}
		
		//<<RENDERIZAMOS PANTALLA PRINCIPAL>>
		renderer.render( _scene, _camera );
		//<<FIN RENDERIZAMOS PANTALLA PRINCIPAL>>
	
		if ( WEBGL.getRenderizarContexto())
		{
			contextViewport.animate();
		}
		
		//return {camera : _camera, scene : _scene};
	};
	
	
	
	
	//-----------------------------------------------------------
	//---------------------- CREAR MUNDO ------------------------
	//-----------------------------------------------------------
	//ahora el codigo comun esta en BuildingScene.js
	function crearMundo(scene){	}

	
	//-----------------------------------------------------------
	//---------------------- CREAR CAMARAS ------------------------
	//-----------------------------------------------------------
	//crea una FLY CAMERA en la escena pasada como parametro
	//<escena> : escena a la que se agregara la camara
	function crearCamaras(escena){
		
		var SCREEN_WIDTH = $(domContainer).width();
		var SCREEN_HEIGHT =  $(domContainer).height();
		//+++++++++ CAMARA CONTEXTO ++++++++++
		_camaraFlyContext = new THREE.PerspectiveCamera( 60, SCREEN_WIDTH / SCREEN_HEIGHT, 50, 1000000 );
		_camaraFlyContext.position.y = 4000;
		
		controlsContext = new FlyControlsPrueba( _camaraFlyContext, domContainer, false);
		controlsContext.movementSpeed = 1000;
		controlsContext.rollSpeed = Math.PI /2;
		controlsContext.autoForward = false;
		controlsContext.dragToLook = false;
		controlsContext.rotarPitch(-Math.PI/2); 
		
		_camaraFlyContext.controls = controlsContext;
		//+++++++++ fin CAMARA CONTEXTO ++++++++++
		
		//+++++++++ CAMARA PRINCIPAL ++++++++++
		_camaraFly = new THREE.PerspectiveCamera( 60, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 1e8 );
		_camaraFly.position.z = 500;
		_camaraFly.position.y = 1500;
		_camaraFly.position.x = 900;				
					
		controls = new FlyControlsPrueba( _camaraFly, domContainer );
//		controls = new FlyControls( _camaraFly, domContainer );
		controls.movementSpeed = 1000;
		controls.rollSpeed = Math.PI /2;
		controls.autoForward = false;
		controls.dragToLook = false;
		
		var rect = 10000;
		controls.setearLimitesCamara (-rect,rect,-rect,rect,-rect,rect);
		controls.lookAtTarget(BUILDING_TARGET_POSITION);//entrada en alem //TODO que en el mapa venga la posicion inicial
		controls.settearCondInic(); 
		//+++++++++ fin CAMARA PRINCIPAL ++++++++++
		
		//+++++++++ Agregamos las camaras a la escena ++++++++++
		escena.add( _camaraFlyContext );
		escena.add( _camaraFly );
		//+++++++++ fin agregamos las camaras a la escena ++++++++++
		
		//+++++++++ Habilitamos los controles para la camara principal ++++++++++
		controls.controlsEnabled = true;
		//+++++++++ fin habilitamos los controles para la camara principal ++++++++++
		
		_camera = _camaraFly;
//		return _camaraFly;
	}
	
	
	//-----------------------------------------------------------
	//---------------------- CREAR LUCES ------------------------
	//-----------------------------------------------------------
	function crearLuces(escena){
            
            ambientLight = new THREE.AmbientLight( 0x111111 );
            pointLight = new THREE.PointLight( 0x555555  );
            pointLight.position.y = 1000;
//            pointLight = new THREE.PointLight( 0x333333  );
            
//            directionalLight = new THREE.DirectionalLight( 0xaaaa99, 1.15);
            directionalLight = new THREE.DirectionalLight( 0xaaaa99, 1);
            directionalLight.position.x = 0;
            directionalLight.position.y = 1;
            directionalLight.position.z = 0;
            directionalLight.position.normalize();
            
            //escena.add( ambientLight );
            escena.add( pointLight );
            escena.add( directionalLight );
            
            
//            directionalLight = new THREE.DirectionalLight( 0xffffff, 0.2);
//            directionalLight.position.x = -1;
//            directionalLight.position.y = -1;
//            directionalLight.position.z = -1;
//            directionalLight.position.normalize();
//            escena.add( directionalLight );
            
            return;
	}
};